package com.telrob.antlr.type;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import com.telrob.antlr.utils.NativeMethod;

public class FunctionBodyType extends XnType {
	private List<XnType> list=new ArrayList<XnType>();
	private String functionName;
	private Map<String,SymbolType>symbol=new HashMap<String, SymbolType>();
	private int symbolCount=0;
	//条件判断
	private int ifIndex=0;
	
	/***
	 * 栈帧中数据的大小
	 * @return
	 */
	public int getSymbolNum() {
		return symbolCount;
	}
	public void addChild(XnType item) {
		list.add(item);
	}
	public FunctionBodyType() {
		super();
	}
	
	public FunctionBodyType(List<XnType> list) {
		super();
		this.list = list;
	}

	public List<XnType> getList() {
		return list;
	}

	public void setList(List<XnType> list) {
		this.list = list;
	}
	
	//处理代码
	public void process() {
		//code.append("test++++++\r\n");
		FunctionType function=(FunctionType)parent;
		FunctionHeaderType header=(FunctionHeaderType)function.getFunctionHeader();
		functionName=((IdType)header.getName()).getName();
		//处理函数头
		FunctionParamType param=(FunctionParamType)header.getParam();
		if(param!=null) {
			List<XnType>paramList=param.getList();
			if(paramList!=null&&paramList.size()>0) {
				int size=paramList.size();
				for(int i=0;i<size;i++) {
					DeclaraType item=(DeclaraType)paramList.get(size-i-1);
					//参数类型
					XnType type=item.getType();
					//参数名字
					IdType name=(IdType)item.getName();
					//int对象类型
					if(type instanceof IntType) {
						String nm=name.getName();
						int index=-i*4-12;
						SymbolType sym=new SymbolType(2, "nm",index);
						symbol.put(nm, sym);
					}
				}
			}
		}
		
		
		
		if(list!=null&&list.size()>0) {
			//针对函数中不同的类型进行处理
			for(XnType item:list) {
				processItem(item);
			}
		}
	}
	private void processFunctionBody(FunctionBodyType body) {
		List<XnType> list=body.getList();
		if(list!=null&&list.size()>0) {
			for(XnType item:list) {
				processItem(item);
			}
		}
	}
	//针对每一项进行处理，便于程序递归遍历
	private void processItem(XnType item) {
		if(item instanceof DeclaraListType) {
			//方法声明
			processDeclaraList((DeclaraListType)item);
		}else if(item instanceof FunctionCallType) {
			//函数调用
			FunctionCallType func=(FunctionCallType)item;
			processFunctionCall(func);
		}else if(item instanceof AssignmentType) {
			//赋值计算
			processAssignmentType((AssignmentType)item);
		}else if(item instanceof ConditionIfBlockType) {
			//if条件判断
			processConditionIfBlockType((ConditionIfBlockType)item);
		}else if(item instanceof ForBlockType) {
			//for循环
			processForBlock((ForBlockType)item);
		}
		//printJson(item);
	}
	
	
	private void processForBlock(ForBlockType item) {
		String nextLabel=functionName+"_"+ifIndex;
		ifIndex++;
		//处理方法参数
		ForConditionBlockType cond=(ForConditionBlockType)item.getCondition();
		XnType p1=cond.getParam1();
		processDeclaraList((DeclaraListType)p1);
		XnType p2=cond.getParam2();
		
		String forStart=functionName+"_"+ifIndex;
		ifIndex++;
		code.append(forStart+":\r\n");
		
		String successLabel=functionName+"_"+ifIndex;
		ifIndex++;
		// TODO 对循环进行处理
		processCondition(p2, code, successLabel, nextLabel, 1);
		code.append(successLabel+":\r\n");
		
		//处理方法体
		XnType body=item.getBody();
		processFunctionBody((FunctionBodyType)body);
		XnType p3=cond.getParam3();
		processAssignmentType((AssignmentType)p3);
		code.append("jmp "+forStart+"\r\n");
		
		code.append(nextLabel+":\r\n");
	}
	/**
	 * 
	 * @param condition 条件 
	 * @param buf 
	 * @param sucessLabel 条件成立跳转
	 * @param nextLabel 条件不城里跳转
	 * @param hasNext 是否有下一个
	 * @param parentOpt 1:没有，2:and，3:or
	 */
	private void processCondition(XnType condition,StringBuffer buf,String successLabel,String nextLabel,Integer parentOpt) {
		//buf.append("-----start-------\r\n");
		if(condition instanceof ConditionBlockType) {
			ConditionBlockType cond=(ConditionBlockType)condition;
			String crtOpt=cond.getOpt();
			XnType val1=cond.getVal1();
			XnType val2=cond.getVal2();
			Integer currentOpt=1;
			if("&&".equals(crtOpt)) {
				currentOpt=2;
			}else if("||".equals(crtOpt)) {
				currentOpt=3;
			}
			String label=functionName+"_"+ifIndex;
			ifIndex+=1;
			String sl=null,nl=null;
			if(parentOpt==1||parentOpt==2) {
				if(currentOpt==2) {
					sl=label;
					nl=nextLabel;
				}else if(currentOpt==3) {
					sl=successLabel;
					nl=label;
				}
			}else if(parentOpt==3) {
				if(currentOpt==2) {
					sl=successLabel;
					nl=nextLabel;
				}else if(currentOpt==3) {
					sl=successLabel;
					nl=label;
				}
			}
			processCondition(val1, buf, sl, nl, currentOpt);
			code.append(label+":\r\n");
			processCondition(val2, buf, successLabel, nextLabel, 1);
			//printJson(condition);
		}else {
			//简单的条件
			ConditionType cond=(ConditionType)condition;
			String opt=cond.getOpt();
			XnType v1=cond.getVal1();
			XnType v2=cond.getVal2();
			if((v1 instanceof ExpressionType)&&(v1 instanceof ExpressionType)) {
				
			}else if(v1 instanceof ExpressionType) {
				
			}else if(v2 instanceof ExpressionType) {
				
			}else {
				//简单的比较指令
				if(v1 instanceof IdType) {
					String name=((IdType)v1).getName();
					SymbolType st=getSymbol(name);
					if(st==null) {
						System.err.println("不能发现改变量:"+name);
						System.exit(0);
					}
					int type=st.getType();
					int index=st.getIndex();
					if(type==1) {
						//全局变量
						buf.append("loadd ax,"+name+"\r\n");
					}else if(type==2) {
						buf.append("loads ax,"+index+"\r\n");
					}else {
						//buf.append("loads ax,"+index+"\r\n");
					}
				}else if(v1 instanceof DigitType) {
					DigitType dt=(DigitType)v1;
					buf.append("movrn ax,"+dt.getValue()+"\r\n");
				}
				
				
				if(v2 instanceof IdType) {
					String name=((IdType)v2).getName();
					SymbolType st=getSymbol(name);
					if(st==null) {
						System.err.println("不能发现改变量:"+name);
						System.exit(0);
					}
					int type=st.getType();
					int index=st.getIndex();
					if(type==1) {
						//全局变量
						buf.append("loadd bx,"+name+"\r\n");
					}else if(type==2) {
						buf.append("loads bx,"+index+"\r\n");
					}else {
						//buf.append("loads ax,"+index+"\r\n");
					}
				}else if(v2 instanceof DigitType) {
					DigitType dt=(DigitType)v2;
					buf.append("movrn bx,"+dt.getValue()+"\r\n");
				}
				buf.append("cmprr ax,bx\r\n");
				
				if(parentOpt==3) {
					String jmp=getOptCode(opt);
					buf.append(jmp+" "+successLabel+"\r\n");
				}else if(parentOpt==2) {
					String jmp=getOptNotCode(opt);
					buf.append(jmp+" "+nextLabel+"\r\n");
				}else if(parentOpt==1) {
					String jmp=getOptNotCode(opt);
					buf.append(jmp+" "+nextLabel+"\r\n");
				}
				
			}
			
			
		}
		//buf.append("-----end--------\r\n");
	}
	
	
	private void processConditionIfBlockType(ConditionIfBlockType item) {
		String endlabel=functionName+"_"+ifIndex;
		ifIndex++;
		//处理if条件
		IfBlockType ift=(IfBlockType)item.getIfCondition();
		XnType condition=ift.getCondition();
		String ifBlockLabel=functionName+"_"+ifIndex;
		ifIndex++;
		StringBuffer buf=new StringBuffer();
		processCondition(condition, buf,ifBlockLabel,endlabel,1);
		//测试
		//code.setLength(0);
		code.append(buf.toString());
		code.append(ifBlockLabel+":\r\n");
		FunctionBodyType body=(FunctionBodyType)ift.getBody();
		processFunctionBody(body);
		//code.append("jmp "+endlabel+"\r\n");
		code.append(endlabel+":\r\n");
		//System.err.println(code.toString());
	}
	//处理赋值语句
	private void processAssignmentType(AssignmentType item) {
		//变量的名字
		String name=item.getName().getName();
		XnType value=item.getValue();
		if(value instanceof ExpressionType) {
			StringBuffer buff=new StringBuffer();
			eachExpression((ExpressionType)value,buff);
			code.append(buff.toString());
			SymbolType sym=getSymbol(name);
			if(sym.getType()==2) {
				code.append("stores "+sym.getIndex()+",dx\r\n");
			}
			// TODO 去全局变量或者其他数据进行处理
		}else if(value instanceof DigitType) {
			String val=((DigitType)value).getValue();
			SymbolType sym=getSymbol(name);
			if(sym==null) {
				System.err.println("未定义变量 "+name);
				System.exit(0);
			}
			int type=sym.getType();
			if(type==1) {
				code.append("movrn dx,"+val+"\r\n");
				code.append("stored "+name+",dx\r\n");
			}else if(type==2) {
				code.append("movrn dx,"+val+"\r\n");
				code.append("stores "+sym.getIndex()+",dx\r\n");
			}
			
		}
		
	}
	
	//处理函数调用
	private void processFunctionCall(FunctionCallType func){
		IdType nameType=(IdType)func.getName();
		//调用函数名称
		String name=nameType.getName();
		FunctionCallParamType param=(FunctionCallParamType)func.getParam();
		param.setParent(this);
		param.process();
		String codeStr=param.getAsmCode();
		if(codeStr!=null&&!"".equals(codeStr)) {
			//System.err.println(codeStr);
			code.append(codeStr);
			//当是本地方法时候
			if(NativeMethod.getInstance().isNative(name)) {
				code.append("calln "+name+"\r\n");
			}else {
				code.append("call "+name+"\r\n");
			}
			List<XnType> pList=param.getList();
			int size=pList.size();
			//堆栈平衡
			code.append("subrn sp,"+size*4+"\r\n");
		}else {
			code.append("call "+name+"\r\n");
		}
		
		//System.err.println(param);
	}
	
	private String processDeclaraList(DeclaraListType typeList) {
		List<XnType> list=typeList.getList();
		if(list!=null&&list.size()>0) {
			for(XnType item:list) {
				//当是初始化
				if(item instanceof DeclaraType) {
					DeclaraType declaraItem=(DeclaraType)item;
					//当时int类型初始化
					if(declaraItem.getType() instanceof IntType) {
						IdType nameType=(IdType)declaraItem.getName();
						String name=nameType.getName();
						declaraItem.getValue();
						if(symbol.get(name)!=null) {
							if(symbol.get(name).getType()!=1) {
								System.err.println(name+"已经定义了");
								System.exit(0);
							}
						}
						symbolCount+=4;
						SymbolType symbolType=new SymbolType(2,name,symbolCount);
						symbol.put(name, symbolType);
						if(declaraItem.getValue() instanceof DigitType) {
							//这种直接在栈帧中存放数据
							DigitType digit=(DigitType)declaraItem.getValue();
							String value=digit.getValue();
							code.append("movrn dx,"+value+"\r\n");
							code.append("stores "+symbolCount+",dx\r\n");
							
						}else if(declaraItem.getValue() instanceof ExpressionType) {
							StringBuffer buff=new StringBuffer();
							ExpressionType exp=(ExpressionType)declaraItem.getValue();
							//是一个表达式
							//printJson(declaraItem.getValue());
							eachExpression(exp,buff);
							code.append(buff.toString());
							code.append("stores "+symbolCount+",dx\r\n");
							//System.err.println(buff.toString());
						}
						
					}
					//printJson(item);
				}
			}
		}
		//System.err.println(code.toString());
		return null;
	}
	
	
	
	@Override
	public SymbolType getSymbol(String name) {
		if(symbol.get(name)!=null) {
			return symbol.get(name);
		}else if(parent!=null) {
			return parent.getSymbol(name);
		}
		return super.getSymbol(name);
	}
	
	
	private String getOptCode(String opt) {
		String jOpt="";
		// je ==,jne != , jg  > , jng <=  , jl  < , jnl >=
		if(opt.equals("==")) {
			jOpt="je";
		}else if(opt.equals("!=")) {
			jOpt="jne";
		}else if(opt.equals(">=")) {
			jOpt="jnl";
		}else if(opt.equals(">")) {
			jOpt="jg";
		}else if(opt.equals("<=")) {
			jOpt="jng";
		}else if(opt.equals("<")) {
			jOpt="jl";
		}
		return jOpt;
	}
	private String getOptNotCode(String opt) {
		String jOpt="";
		// je ==
		// jne !=
		// jg  >
		// jng <=
		// jl  <
		// jnl >=
		if(opt.equals("==")) {
			jOpt="jne";
		}else if(opt.equals("!=")) {
			jOpt="je";
		}else if(opt.equals(">=")) {
			jOpt="jl";
		}else if(opt.equals(">")) {
			jOpt="jng";
		}else if(opt.equals("<=")) {
			jOpt="jg";
		}else if(opt.equals("<")) {
			jOpt="jnl";
		}
		return jOpt;
	}
	
	@Override
	public String toString() {
		return "FunctionBodyType [list=" + list + "]";
	}
}
